
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <termio.h>
#include <time.h>

/*
*
*  读取uart上报环境数据应用代码
*/



static int baudflag_arr[] = {
    B921600, B460800, B230400, B115200, B57600, B38400,
    B19200,  B9600,   B4800,   B2400,   B1800,  B1200,
    B600,    B300,    B150,    B110,    B75,    B50
};
static int speed_arr[] = {
    921600,  460800,  230400,  115200,  57600,  38400,
    19200,   9600,    4800,    2400,    1800,   1200,
    600,     300,     150,     110,     75,     50
};

int speed_to_flag(int speed)
{
    int i;
 
    for (i = 0;  i < sizeof(speed_arr)/sizeof(int);  i++) {
        if (speed == speed_arr[i]) {
            return baudflag_arr[i];
        }
    }
 
    fprintf(stderr, "Unsupported baudrate, use 9600 instead!\n");
    return B9600;
}

static struct termio oterm_attr;


//串口设置
int setup_port(int fd, int baud, int databits, int parity, int stopbits)
{
    struct termio term_attr;
 
    
    if (ioctl(fd, TCGETA, &term_attr) < 0) {
        return -1;
    }
 
    
    memcpy(&oterm_attr, &term_attr, sizeof(struct termio));
 
    term_attr.c_iflag &= ~(INLCR | IGNCR | ICRNL | ISTRIP);
    term_attr.c_oflag &= ~(OPOST | ONLCR | OCRNL);
    term_attr.c_lflag &= ~(ISIG | ECHO | ICANON | NOFLSH);
    term_attr.c_cflag &= ~CBAUD;
    term_attr.c_cflag |= CREAD | speed_to_flag(baud);
 
    
    term_attr.c_cflag &= ~(CSIZE);
    switch (databits) {
        case 5:
            term_attr.c_cflag |= CS5;
            break;
 
        case 6:
            term_attr.c_cflag |= CS6;
            break;
 
        case 7:
            term_attr.c_cflag |= CS7;
            break;
 
        case 8:
        default:
            term_attr.c_cflag |= CS8;
            break;
    }
 
    
    switch (parity) {
        case 1:  
            term_attr.c_cflag |= (PARENB | PARODD);
            break;
 
        case 2:  
            term_attr.c_cflag |= PARENB;
            term_attr.c_cflag &= ~(PARODD);
            break;
 
        case 0:  
        default:
            term_attr.c_cflag &= ~(PARENB);
            break;
    }
 
 
    
    switch (stopbits) {
        case 2:  
            term_attr.c_cflag |= CSTOPB;
            break;
 
        case 1:  
        default:
            term_attr.c_cflag &= ~CSTOPB;
            break;
    }
 
    term_attr.c_cc[VMIN] = 1;
    term_attr.c_cc[VTIME] = 0;
 
    if (ioctl(fd, TCSETAW, &term_attr) < 0) {
        return -1;
    }
 
    if (ioctl(fd, TCFLSH, 2) < 0) {
        return -1;
    }
 
    return 0;
}
 
 
void print_usage(char *program_name)
{
    fprintf(stderr,
            "*************************************\n"
            "  A Simple Serial Port Test Utility\n"
            "*************************************\n\n"
            "Usage:\n  %s <device> <baud> <databits> <parity> <stopbits> \n"
            "       databits: 5, 6, 7, 8\n"
            "       parity: 0(None), 1(Odd), 2(Even)\n"
            "       stopbits: 1, 2\n"
            "Example:\n  %s /dev/ttyUSB0 115200 8 0 1\n\n",
            program_name, program_name
           );
}


int main(int argc, char *argv[]) //./a.out /dev/ttyS4 115200 8 0 1
{
    int fd;
    int baud;
    int len;
    int databits;
    int stopbits;
    int parity;

    if (argc != 6) {
        print_usage(argv[0]);
        return 1;
    }
    ///a.out /dev/ttyS4 115200 8 0 1
    baud = 115200;//获取波特率
    if ((baud < 0) || (baud > 921600)) {
        fprintf(stderr, "Invalid baudrate!\n");
        return 1;
    }
 
    databits = 8; //获取数据位
    if ((databits < 5) || (databits > 8)) {
        fprintf(stderr, "Invalid databits!\n");
        return 1;
    }
 
    parity = 0; //获取奇偶校验位
    if ((parity < 0) || (parity > 2)) {
        fprintf(stderr, "Invalid parity!\n");
        return 1;
    }
 
    stopbits = 1; //获取停止位
    if ((stopbits < 1) || (stopbits > 2)) {
        fprintf(stderr, "Invalid stopbits!\n");
        return 1;
    }
 
    // 打开/dev/ttyUSB0
    fd = open(argv[1], O_RDWR, 0); //打开串口设备文件
    if (fd < 0) {
        fprintf(stderr, "open <%s> error %s\n", argv[1], strerror(errno));
        return 1;
    }
 
    if (setup_port(fd, baud, databits, parity, stopbits)) { //设置串口
        fprintf(stderr, "setup_port error %s\n", strerror(errno));
        close(fd);
        return 1;
    }
	
	unsigned char vbuf[20];
	
	unsigned char byte = 0, synok = 0;
	int i = 0;
	while (1) {
		bzero(vbuf, 20);
		i = 0;
		//循环读取一个数据包		
		byte = 0;
		read(fd, &byte,1);
		i++;
		printf("no. %d %02x\n", i, byte);
		if (byte == 0x01) {
			byte = 0;
			read(fd, &byte, 1);
			i++;
			printf("no. %d %02x\n", i, byte);
			if (byte == 0xFE) {				
				while (1) {
					byte = 0;
					read(fd, &byte, 1);
					if (byte == 0x01) { 	//==========灯光处理
						vbuf[1] = byte; 	//节点类型1						
						byte = 0;
						read(fd, &byte, 1);
						if (byte == 0x82) { //灯光心跳
							vbuf[0] = 7; //一共有7个字节
							vbuf[2] = byte; //命令字1
							byte = 0;
							read(fd, &byte, 1);
							vbuf[3] = byte; //节点地址1
							byte = 0;
							read(fd, &byte, 1);
							vbuf[4] = byte; //节点地址1
							//校验和2
							byte = 0;
							read(fd, &byte, 1);
							vbuf[5] = byte; //校验和1
							byte = 0;
							read(fd, &byte, 1);
							vbuf[6] = byte; //校验和1
							//数据
							byte = 0;
							read(fd, &byte, 1);
							vbuf[7] = byte; 
							break;
						} //byte == 0x82 心跳 endif

						if (byte == 0x03) { //灯光上传数据
							vbuf[0] = 9; //一共有9个字节
							vbuf[2] = byte; //命令字1
							byte = 0;
							read(fd, &byte, 1);
							vbuf[3] = byte; //节点地址1
							byte = 0;
							read(fd, &byte, 1);
							vbuf[4] = byte; //节点地址1
							//校验和2
							byte = 0;
							read(fd, &byte, 1);
							vbuf[5] = byte; //校验和1
							byte = 0;
							read(fd, &byte, 1);
							vbuf[6] = byte; //校验和1
							//数据
							byte = 0;
							read(fd, &byte, 1);
							vbuf[7] = byte; 
							byte = 0;
							read(fd, &byte, 1);
							vbuf[8] = byte; 
							byte = 0;
							read(fd, &byte, 1);
							vbuf[9] = byte; 
							break;
						} //byte == 0x82 灯光上传数据endif
						
					} //byte == 0x01 灯光 处理 endif
#if 1
					if (byte == 0x02) { 	//==============电机处理
						vbuf[1] = byte; 	//节点类型1						
						byte = 0;
						read(fd, &byte, 1);
						if (byte == 0x82) { //电机心跳
							vbuf[0] = 7; //一共有7个字节
							vbuf[2] = byte; //命令字1
							byte = 0;
							read(fd, &byte, 1);
							vbuf[3] = byte; //节点地址1
							byte = 0;
							read(fd, &byte, 1);
							vbuf[4] = byte; //节点地址1
							//校验和2
							byte = 0;
							read(fd, &byte, 1);
							vbuf[5] = byte; //校验和1
							byte = 0;
							read(fd, &byte, 1);
							vbuf[6] = byte; //校验和1
							//数据
							byte = 0;
							read(fd, &byte, 1);
							vbuf[7] = byte; 
							break;
						} //byte == 0x82 电机心跳 endif

						if (byte == 0x03) { //电机上传数据
							vbuf[0] = 7; //一共有7个字节
							vbuf[2] = byte; //命令字1
							byte = 0;
							read(fd, &byte, 1);
							vbuf[3] = byte; //节点地址1
							byte = 0;
							read(fd, &byte, 1);
							vbuf[4] = byte; //节点地址1
							//校验和2
							byte = 0;
							read(fd, &byte, 1);
							vbuf[5] = byte; //校验和1
							byte = 0;
							read(fd, &byte, 1);
							vbuf[6] = byte; //校验和1
							//数据
							byte = 0;
							read(fd, &byte, 1);
							vbuf[7] = byte; 
							
							break;
						} //byte == 0x03 电机上传数据endif
						
					} //byte == 0x02 电机处理

#endif				

					if (byte == 0x05) { 	//=================温湿度处理
						vbuf[1] = byte; 	//节点类型1						
						byte = 0;
						read(fd, &byte, 1);
						if (byte == 0x82) { //温湿度心跳
							vbuf[0] = 7; //一共有7个字节
							vbuf[2] = byte; //命令字1
							byte = 0;
							read(fd, &byte, 1);
							vbuf[3] = byte; //节点地址1
							byte = 0;
							read(fd, &byte, 1);
							vbuf[4] = byte; //节点地址1
							//校验和2
							byte = 0;
							read(fd, &byte, 1);
							vbuf[5] = byte; //校验和1
							byte = 0;
							read(fd, &byte, 1);
							vbuf[6] = byte; //校验和1
							//数据
							byte = 0;
							read(fd, &byte, 1);
							vbuf[7] = byte; 
							break;
						} //byte == 0x82 温湿度心跳 endif

						if (byte == 0x03) { //温湿度上传数据
							vbuf[0] = 8; //一共有8个字节
							vbuf[2] = byte; //命令字1
							byte = 0;
							read(fd, &byte, 1);
							vbuf[3] = byte; //节点地址1
							byte = 0;
							read(fd, &byte, 1);
							vbuf[4] = byte; //节点地址1
							//校验和2
							byte = 0;
							read(fd, &byte, 1);
							vbuf[5] = byte; //校验和1
							byte = 0;
							read(fd, &byte, 1);
							vbuf[6] = byte; //校验和1
							//数据
							byte = 0;
							read(fd, &byte, 1);
							vbuf[7] = byte; 
							byte = 0;
							read(fd, &byte, 1);
							vbuf[8] = byte; 
							break;
						} //byte == 0x03 温湿度上传数据endif
						
					} //byte == 0x05   温湿度处理
					
				} // end while (1)  循环读取一个数据包
				for (i = 0; i < vbuf[0]; i++) {
					printf("%02x ", vbuf[i+1]);
				}
				printf("cnt = %d\n", vbuf[0]);
				

			}//byte == 0xEF endif

		} //byte == 0x01 endif
	}
	
    close(fd);
 
    return 0;
}

